/**
 * theme：甘特图插件
 *author：杨波
 * date：2018-11-12
 * versions：1.0.0
 */
(function($){
	var language = {
		ch:{
			month: ['一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'],
			week: ["日", "一", "二", "三", "四", "五", "六"]
		}
	}
	var head_height = {
		yaer: 1,
		month: 2,
		day: 3,
		week: 4,
	}
	var gantt = function (target){
		this.target = target;
		this.state = $.data(target, 'ybgantt').options;
		this.init();
        this.state.obj = this;
	};
	gantt.prototype = {
		x: 0,
		id: '',
        back: null,
		allTask: [],
		state: null,
		target: null,
		gridWidth: 0,
		taskIdList:[],
		allDateArr: null,
		init: function(){
			this._create();
		},
		_create: function(){
			var html = '<div class="ybgantt-head">';
			html += this._create_head_left();
			html += this._create_head_right();
			html += '</div>';
			html += '<div class="ybgantt-body">';
			html += this._create_body_left();
			html += this._create_body_right();
			html += '</div>';
			html += '<div class="ybgantt-foot">';
			html += this._create_scroll();
			html += '</div>';
			$(this.target).append(html);
			this._setCss();
			this._count_splitLine_height();
			this._setDrag();
			this._unbindTas();
		},
		_create_head_left: function(){
			var html = '<div class="ybgantt-left">';
			html += '<div class="ybgantt-triangle">';
			html += '<div class="ybgantt-triangle-splitLine"></div>';
			html += '<div class="ybgantt-triangle-bottomleft">日期</div>';
			if(!this.state.title){
				this.state.title = '列表';
			}
			html += '<div class="ybgantt-triangle-topright">' + this.state.title + '</div>';
			html += '</div>';
			html += '<div class="ybgantt-left-title">';
			if(this.state.isShowFiled){
				this.gridWidth = 0;
				html += '<div class="ybgantt-row" style="height:' + this.state.height + 'px;">';
				html += this._create_colum_title(this.state.filed);
				html += '</div>';
			}
			html += '</div>';
			html += '</div>';
			return html;
		},
		_create_head_right: function(){
			var level = head_height[this.state.level];
			if(this.allDateArr == null){
				this._getAllDate(this.state.startDate,this.state.endDate,level);
			}
			var html = '<div class="ybgantt-right">';
			html += '<div class="ybgantt-content-scroll">';
			var width = 0,columns = '';
			if(level >= 1){
				for(var key in this.allDateArr.year){
					width += this.allDateArr.year[key] * this.state.width;
					columns += '<div class="ybgantt-column" style="line-height:' + this.state.height + 'px;width:' + (this.allDateArr.year[key] * this.state.width) + 'px;">' + key + '</div>';
				}
				html += '<div class="ybgantt-row" style="height:' + this.state.height + 'px;width:' + width + 'px">';
				html += columns;
				html += '</div>';
			}
			if(level >= 2){
				columns = '';
				for(var key in this.allDateArr.month){
					var showText = key.split("-");
					columns += '<div class="ybgantt-column" style="line-height:' + this.state.height + 'px;width:' + (this.allDateArr.month[key] * this.state.width) + 'px;">' + language.ch.month[parseInt(showText[1])] + '</div>';
				}
				html += '<div class="ybgantt-row" style="height:' + this.state.height + 'px;width:' + width + 'px">';
				html += columns;
				html += '</div>';
			}
			if(level >= 3){
				columns = '';
				for(var key in this.allDateArr.day){
					var showText = key.split("-");
					columns += '<div class="ybgantt-column" style="line-height:' + this.state.height + 'px;width:' + (this.allDateArr.day[key] * this.state.width) + 'px;">' + showText[2] + '</div>';
				}
				html += '<div class="ybgantt-row" style="height:' + this.state.height + 'px;width:' + width + 'px">';
				html += columns;
				html += '</div>';
			}
			if(level >= 4){
				columns = '';
				var week = 0;
				for(var key in this.allDateArr.day){
					var showText = key.split("-");
					columns += '<div class="ybgantt-column" style="line-height:' + this.state.height + 'px;width:' + (this.allDateArr.day[key] * this.state.width) + 'px;">' + showText + '</div>';
				}
				html += '<div class="ybgantt-row" style="height:' + this.state.height + 'px;width:' + width + 'px">';
				html += columns;
				html += '</div>';
			}
			html += '</div>';
			html += '</div>';
			return html;
		},
		_create_body_left: function(){
			if(this.gridWidth == 0){
				this._create_colum_title(this.state.filed);
			}
			var html = '',height = 0;;
			for(var i = 0; i < this.state.data.length; i++){
				var child= this._create_grid_item(this.state.data[i],this.state.filed,'-' + i);
				html += '<div class="ybgantt-row" style="display:flex;width:100%;height: ' + child.height +'px;">';
				html += child.html;
				html += '</div>';
				height += child.height;
			}
			height = height == 0 ? 'auto' : (height + 'px;');
			html = '<div class="ybgantt-left" style="display:block;height:' + height + '">' + html + '</div>';
			return html;
		},
		_create_body_right: function(){
			var width = 0;
			for(var key in this.allDateArr.year){
				width += this.allDateArr.year[key] * this.state.width;
			}
			var columns = this._create_drop_div(this.state.data,this.state.filed,width,'');
			columns.height = columns.height == 0 ? 'auto' : (columns.height + 'px;');
            var html = '<div class="ybgantt-right ybgantt-content-scroll" style="height: ' + columns.height + '">';
            html += '<div class="ybgantt-scroll-touch" style="display: inline;background: transparent;">';
			html += columns.html;
            html += '</div>';
            html += '</div>';
			return html;
		},
		_create_scroll: function(){
			var width = 0;
			for(var key in this.allDateArr.year){
				width += this.allDateArr.year[key] * this.state.width;
			}
			var html = '<div class="ybgantt-left">';
			html += '<div class="ybgantt-conten"></div>';
			html += '</div>';
			html += '<div class="ybgantt-right">';
			html += '<div class="ybgantt-scroll">';
			html += '<div class="ybgantt-conten" style="width: ' + width + 'px;height: 1px;"></div>';
			html += '</div>';
			html += '</div>';
			return html;
		},
		_create_colum_title: function(filed){
			var html = '';
			for(var i = 0; i < filed.columns.length; i++){
				var item = filed.columns[i];
				if(!item.width){
					item.width = this.state.width * 2;
				}
				this.gridWidth += item.width;
				html += '<div class="ybgantt-column" style="line-height:' + this.state.height + 'px;width:' + item.width + 'px;">' + item.name + '</div>';
			}
			if(filed.childdren){
				html += this._create_colum_title(filed.childdren);
			}
			return html;
		},
		_getAllDate: function (start,end,level){
			var allDateArr = {
				year:{},
				month:{},
				day:{}
			};
			var ab = start.split("-");
			var ae = end.split("-");
			if(level >= 3){
				var unixDb=new Date(start).getTime();
				var unixDe=new Date(end).getTime();
				for(var k=unixDb;k<=unixDe;){
					var date_item = this._dateFormat(new Date(parseInt(k)),level),date_item_str = date_item.split("-");

					if(allDateArr.year[date_item_str[0]]){
						allDateArr.year[date_item_str[0]]++;
					} else {
						allDateArr.year[date_item_str[0]] = 1;
					}

					if(allDateArr.month[date_item_str[0] + "-" + date_item_str[1]]){
						allDateArr.month[date_item_str[0] + "-" + date_item_str[1]]++;
					} else {
						allDateArr.month[date_item_str[0] + "-" + date_item_str[1]] = 1;
					}

					if(allDateArr.day[date_item]){
						allDateArr.day[date_item]++;
					} else {
						allDateArr.day[date_item] = 1;
					}

					k=k+24*60*60*1000;
				}
			} else if(level == 2){
				if (parseInt(ab[0]) < parseInt(ae[0])) {
					mCount = (parseInt(ae[0]) - parseInt(ab[0])) * 12 + parseInt(ae[1]) - parseInt(ab[1])+1;
				} else {
					mCount = parseInt(ae[1]) - parseInt(ab[1])+1;
				}
				if (mCount > 0) {
					var startM = parseInt(ab[1]);
					var startY = parseInt(ab[0]);
					for (var i = 0; i < mCount; i++) {
						allDateArr.month[startY + "-" + startM] = 1;
						if(allDateArr.year[startY]){
							allDateArr.year[startY]++;
						} else {
							allDateArr.year[startY] = 1;
						}
						if (startM < 12) {
							startM += 1;
						} else {
							startM = 1;
							startY += 1;
						}
					}
				}
			} else{
				var mYearCount = parseInt(ae[0]) - parseInt(ab[0])+1;
				var startY = parseInt(ab[0]);
				for (var i = 0; i < mYearCount;i++) {
					allDateArr.year[startY] = 1;
					startY += 1;
				}
			}

			this.allDateArr = allDateArr;
		},
		_dateFormat: function(date,level){
			var s='';
			if(level >= 1){
				s+=date.getFullYear()+'-';          // 获取年份。
			}
			if(level >= 2){
				s+=(date.getMonth()+1)+"-";         // 获取月份。
			}
			if(level >= 3){
				s+= date.getDate();                 // 获取日。
			}
			return(s);                          // 返回日期。
		},
		_count_splitLine_height: function(){
			var height = $(this.target).find(".ybgantt-triangle").height();
			var width = $(this.target).find(".ybgantt-triangle").width();
			$(this.target).find(".ybgantt-triangle-splitLine").width(height + width);
			var angle = 180 * Math.atan2(height,width)/Math.PI;
			$(this.target).find(".ybgantt-triangle-splitLine").css({
				'transform': 'rotate(' + angle + 'deg)',
				'-ms-transform': 'rotate(' + angle + 'deg)',
				'-moz-transform': 'rotate(' + angle + 'deg)',
				'-webkit-transform': 'rotate(' + angle + 'deg)',
				'-o-transform': 'rotate(' + angle + 'deg)'
			});
		},
		_create_grid_item: function(data,filed,parentId){
			var html = '',childHmlt = '',height = 0,allHeight = 0;

			if(!data[filed.childCloumn] || data[filed.childCloumn].length == 0){
				data[filed.childCloumn] = [{}];
			}
			if(filed.childdren){
				childHmlt += '<div class="ybgantt-column" style="flex:1;">';
				for(var i = 0; i < data[filed.childCloumn].length; i++){
					var result = this._create_grid_item(data[filed.childCloumn][i],filed.childdren,parentId + '-' + i);
					childHmlt += '<div class="ybgantt-column-group" style="height:' + result.height + 'px">';
					childHmlt += result.html;
					height += result.height;
					childHmlt += '</div>';
				}
				childHmlt += '</div>';
			} else {
				height = this.state.height;
			}

			for(var i = 0; i < filed.columns.length; i++){
				var item = filed.columns[i],showText = data[item.column]?data[item.column] : '';
				if(!item.width){
					item.width = this.state.width * 2;
				}
				html += '<div class="ybgantt-column' + (item.isDrag ? ' drag' : '') + '" id="drag' + parentId + '" style="line-height:' + height + 'px;height: ' + height + 'px;width:' + item.width + 'px;">' + showText + '</div>';
			}
			return {html:html + childHmlt,height:height};
		},
		_create_drop_div: function(data,filed,width,parentId){
			var html = '',height = 0;
			if(data){
				for(var i = 0; i < data.length; i++){
					var child = {html: '',height: this.state.height};
					if(filed.childdren){
						child = this._create_drop_div(data[i][filed.childCloumn],filed.childdren,width,parentId + "-" + i);
					} else if(data[i][this.state.sDate] != null && data[i][this.state.sDate]){
						this.x = this._getCor_x_by_date(data[i][this.state.sDate]);
						child.html =this._create_task_item("pro" + parentId + "-" + i,filed,data[i]);
						this.taskIdList.push(parentId + "-" + i);
					}
					html += '<div class="ybgantt-row" id="drop' + (parentId + "-" + i) + '" style="height: ' + child.height + 'px;width: ' + width + 'px">';
					html += child.html;
					height += child.height;
					html += '</div>';
				}
			}
			return {html:html,height:height};
		},
		_setCss: function(){
			$(this.target).find('.ybgantt-left').css('width',this.gridWidth);
			$(this.target).find('.ybgantt-body .ybgantt-right').css('background-size',this.state.width + 'px ' + this.state.height + 'px');
		},
		_setDrag: function (){
			var self = this;
			$(self.target).on('mouseenter','.drag',function(e){
                self.back = null;
				var id =e.target.id.replace(/drag/, "drop");
				if(!e.target.isDrag){
					$(e.target).attr("draggable",true);
					$('#' + id).addClass('drop');
					$('#' + id).bind('drop',function(ev){
						self.id = id;
						ev.preventDefault();
					});
					$('#' + id).bind('dragover',function(ev){
						ev.preventDefault();
					});
				}
			});
			$(self.target).on('mouseleave','.drag',function(e){
				if(!e.target.isDrag){
					var id =e.target.id.replace(/drag/, "drop");
					$(e.target).removeAttr('draggable');
					$('#' + id).removeClass('drop');
					$('#' + id).unbind('drop');
					$('#' + id).unbind('dragover');
				}
			});
			document.addEventListener("drop",function (ev) {
				var evTarget = ev || window.event;
				self.x = ev.offsetX;
				self._getTaskData(self.id);
			});
			$(self.target).on('mousedown','.ybgantt-task',function(e){
				var target = $(e.target);
				if(!target.hasClass('ybgantt-task')){
					target = target.parent();
				};
                self.back = null;
				var offsetX = e.offsetX,pageX = e.pageX;
                target.parent().addClass('drop');
				$(self.target).find('.ybgantt-scroll-touch').mousemove(function(ev){
					target.offset({
						left:ev.pageX - offsetX
					});
                    var left = parseFloat(target.css("left")),width = target.width(),pwidth = target.parent().width();
                    if(left < 0){
                        target.offset({
                            left:ev.pageX - offsetX - left
                        });
                    } else if(left + width > pwidth){
                        target.offset({
                            left:ev.pageX - offsetX - (left + width - pwidth)
                        });
                    }
				});
                $(self.target).find('.ybgantt-scroll-touch').mouseleave(function(){
					isDrag();
					self._count_left(target);
                    $(this).off('mousemove');
                    $(this).off('mouseleave');
                    $(this).off('mouseup');
                    target.parent().removeClass('drop');
				});
                $(self.target).find('.ybgantt-scroll-touch').mouseup(function(){
					isDrag();
                    self._count_left(target);
                    $(this).off('mousemove');
                    $(this).off('mouseleave');
                    $(this).off('mouseup');
                    target.parent().removeClass('drop');
                });
                function isDrag() {
					var strs = target[0].id.split('-'),
						nowData = self.state.data,
						nowFiled = self.state.filed;
					for(var i = 1; i < strs.length; i++){
						if(i != 1){
							nowData = nowData[nowFiled.childCloumn][parseInt(strs[i])];
							nowFiled = nowFiled.childdren;
						} else {
							nowData = nowData[parseInt(strs[i])];
						}
					}

					nowData[self.state.sDate] = self._get_date_by_x(parseFloat(target.css("left"))).date;

					var _data = self._setDateVal(strs,1,self.state.data,self.state.filed,nowData);

					var boo = true;
					if(self.state.onAllowDrop != null){
						if(typeof self.state.onAllowDrop != 'function'){
							boo = false;
						} else if(self.state.onAllowDrop(nowData) === false) {
							boo = false;
						}
					}
					if(boo){
						self.state.data = _data;
						self.back = function () {
							target.offset({
								left:pageX
							});
						}
					} else {
						target.offset({
							left:pageX
						});
					}
				}
			});
			$(self.target).on('mouseup','.ybgantt-task',function(e){
				var target = $(e.target);
				if(!target.hasClass('ybgantt-task')){
					target = target.parent();
				}
                $(self.target).find('.ybgantt-scroll-touch').off('mousemove');
                $(self.target).find('.ybgantt-scroll-touch').off('mouseleave');
                $(self.target).find('.ybgantt-scroll-touch').off('mouseup');
                target.parent().removeClass('drop');
                self._count_left(target);
			});

			$(self.target).find('.ybgantt-scroll').scroll(function(e){
				var scrollLeft = this.scrollLeft;
				$(self.target).find('.ybgantt-content-scroll').each(function(index, element) {
					this.scrollLeft = scrollLeft;
				});
			});
			$(self.target).on('click','.ybgantt-task',function(e){var target = $(e.target);
                if(!target.hasClass('ybgantt-task')){
                    target = target.parent();
                };
				var strs = target[0].id.split('-'),
					nowData = self.state.data,
					nowFiled = self.state.filed;
				for(var i = 1; i < strs.length; i++){
					if(i != 1){
						nowData = nowData[nowFiled.childCloumn][parseInt(strs[i])];
						nowFiled = nowFiled.childdren;
					} else {
						nowData = nowData[parseInt(strs[i])];
					}
				}
				if(self.state.onClick){
					self.state.onClick(nowData);
				}
			});
		},
		_getTaskData: function(id){
			this.allTask = [];
			var strs = id.split('-'),
				nowData = this.state.data,
				nowFiled = this.state.filed;
			for(var i = 1; i < strs.length; i++){
				if(i != 1){
					nowData = nowData[nowFiled.childCloumn][parseInt(strs[i])];
					nowFiled = nowFiled.childdren;
				} else {
					nowData = nowData[parseInt(strs[i])];
				}
			}
			var nowData = this._get_task_childData(id,nowFiled,nowData);
			var _data = this._setDateVal(strs,1,this.state.data,this.state.filed,nowData);


			var boo = true;
			if(this.state.onAllowDrop != null){
				if(typeof this.state.onAllowDrop != 'function'){
					boo = false;
				} else if(this.state.onAllowDrop(nowData) === false) {
					boo = false;
				}
			}
			if(boo){
                this.state.data = _data;
				for(var i = 0; i < this.allTask.length; i++){
					this.allTask[i].target.append(this.allTask[i].html);
				}
				$('#' + id).removeClass('drop');
				$('#' + id).unbind('drop');
				$('#' + id).unbind('dragover');
				var id = id.replace(/drop/, "drag");
                $('#' + id).parent().find('.drag').addClass("removeDrag");
                $('#' + id).parent().find('.drag').removeClass("drag");
                $('#' + id).parents(".ybgantt-column").siblings(".drag").addClass("removeDrag");
				$('#' + id).parents(".ybgantt-column").siblings(".drag").removeClass("drag");
				
				this.back = function () {
                    $('#' + id).parent().find('.removeDrag').addClass("drag");
                    $('#' + id).parents(".ybgantt-column").siblings(".removeDrag").addClass("drag");
                    for(var i = 0; i < this.allTask.length; i++){
                        this.allTask[i].target.find(".ybgantt-task").remove();
                    }
                }
			}
		},
        _setDateVal:function setDateVal(strs,index,data,filed,nowData){
            if(index == strs.length){
                data = nowData;
            } else if(index != 1){
                data[filed.childCloumn][parseInt(strs[index])] = this._setDateVal(strs,index + 1,data[filed.childCloumn][parseInt(strs[index])],filed.childdren,nowData);
            } else {
                data[parseInt(strs[index])] = this._setDateVal(strs,index + 1,data[parseInt(strs[index])],filed,nowData);
            }
            return data;
        },
		_get_task_childData: function(id,filed,data){
			if(filed.childdren){
				if(data[filed.childCloumn]){
					for(var i = 0; i < data[filed.childCloumn].length;i++){
						data[filed.childCloumn][i] = this._get_task_childData(id + "-" + i,filed.childdren,data[filed.childCloumn][i]);
					}
				}
			} else {
				var obj = this._get_date_by_x(this.x);
				this.x = obj.x;
				data[this.state.sDate] = obj.date;
				var html = this._create_task_item(id.replace(/drop/, "pro"),filed,data);
				this.allTask.push({target: $("#" + id),html:html});
				this.x += data[this.state.dayClumn] * this.state.width;
			}
			return data;
		},
		_create_task_item: function (id,filed,data){
			var html = '';
			if(!filed.childdren){
				for(var i = 0; i < filed.columns.length; i++){
					var item = filed.columns[i];
					if(item.proShow){
						html = '<div id="' + id + '" class="ybgantt-task" style="width: ' + (data[this.state.dayClumn] * this.state.width) + 'px;left: ' + this.x + 'px">';
						html += '<div class="ybgantt-task-showText" title="' + data[item.column] +'">' + data[item.column] + '</div>';
						html += '<div class="ybgantt-task-progress" style="' + ((this.state.proClumn != null && data[this.state.proClumn]) ? ('width: ' + data[this.state.proClumn] + '%;') : 'display:none') + '"></div>';
						html += '</div>';
						break;
					}
				}
			}
			return html;
		},
		_getCor_x_by_date:function (date){
			var unixDb = (new Date(this.state.startDate)).getTime(),
				unixDe = (new Date(date)).getTime(),
				x = 0;
			for(var k=unixDb;k<=unixDe;){
				x += this.state.width;
				k=k+24*60*60*1000;
			}
			return x;
		},
		_get_date_by_x: function(x){
			var level = head_height[this.state.level],key = this.state.level;
			if(level > 3){
				key = 'day';
			}
			var i = 0;
			var dates = this.allDateArr[key];
			for(var key_date in dates){
				i += dates[key_date] * this.state.width;
				if(i > x){
					return {date:key_date,x:i-dates[key_date] * this.state.width};
				}
			}
		},
		_count_left: function(target){
			var left = parseFloat(target.css("left"));
			left = left % this.state.width == 0?left:(left - left % this.state.width);
			$(target).css("left",left + "px");
		},
		_unbindTas: function(){
			for(var i = 0; i < this.taskIdList.length; i++){
				var id = this.taskIdList[i];
				$('#drop' + id).removeClass('drop');
				$('#drop' + id).unbind('drop');
				$('#drop' + id).unbind('dragover');
                $('#drag' + id).parent().find('.drag').addClass("removeDrag");
                $('#drag' + id).parent().find('.drag').removeClass("drag");
                $('#drag' + id).parents(".ybgantt-column").siblings(".drag").addClass("removeDrag");
				$('#drag' + id).parents(".ybgantt-column").siblings(".drag").removeClass("drag");
			}
		},
	};
	$.fn.ybgantt = function(options, param){
		if (typeof options == 'string'){
			return $.fn.ybgantt.methods[options](this, param);
		}
		options = options || {};
		return this.each(function(){
			var state = $.data(this, 'ybgantt');
			if (state){
				$.extend(state.options, options);
			} else {
				$.data(this, 'ybgantt', {
					options: $.extend({}, $.fn.ybgantt.defaults, options),
					ybgantt: $(this).addClass('ybgantt')
				});
				var demo = new gantt(this);
			}
		});
	};

	$.fn.ybgantt.methods = {
        back: function (jq,boo) {
            var state = $.data(jq[0], 'ybgantt').options;
            if(state.obj.back != null && boo){
                state.obj.back();
            }
        }
	};

	$.fn.ybgantt.defaults = {
		data: [],
		startDate: null,
		endDate: null,
		filed:null,
		level: 'day',
		height: 40,
		width: 40,
		gridWidth: 400,
		language: 'ch',
		title: null,
		proClumn: null,
		dayClumn: null,
		sDate: 'startDate',
		isShowFiled: false,
		onAllowDrop: null,
		onClick: null,
	};
})(jQuery);